from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext.db import djangoforms
from imdb import IMDb
import response

import sys
import logging

logger = logging.getLogger(__name__)

class Dvd(db.Model):
    title = db.StringProperty(required=True)
    actors = db.StringListProperty()
    directors = db.StringListProperty()
    musicDirectors = db.StringListProperty()
    year = db.StringProperty()
    type = db.StringProperty()
    imdbLink = db.StringProperty()
    thumbNailLink = db.StringProperty()
    
    owner = db.UserProperty()

    created = db.DateTimeProperty(auto_now_add=True)
    modified = db.DateTimeProperty(auto_now=True)

class DvdForm(djangoforms.ModelForm):
    class Meta:
        model = Dvd
        exclude = ['owner', 'created', 'modified']
        
def myDvdList(request):
    logger.info('[Trace] Entering myDvdList...')
    user = users.GetCurrentUser()
    if user is None:
        logger.info('User is not logged in... redirecting...')
        return response.login(request)
    if user:
        logger.info('Logged in as user -> (%s)' % (str(user)))
        try:
            logger.info('Retrieving user item list from db...')
            dvds = db.GqlQuery('SELECT * FROM Dvd WHERE owner = :1 ORDER BY created DESC', user)
            logger.info('Done...')
            params={}
            logger.info('Parsing result...')
            params['dvd_list'] = getDvdJsonList(dvds)
            logger.info('Done...')
            return response.respond(request, user, 'dvdListJson', params)
        except Exception, e:
            logger.error(sys.exc_info())
            statusStr = 'Exception throw while retrieving list for user (%s). Reason (%s)' % (str(user), str(e))
            return response.done(request, user, "{\"status\":\"" + statusStr + "\"}")
        
def getDvdJsonList(dvds):
    logger.info('[Trace] Entering myDvdList...')
    dvdJsonList=[]
    for dvd in dvds:
        dvdJsonList.append(getDvdJson(dvd, dvd.key()))
    return dvdJsonList

def getDvdJson(dvd, key):
    logger.info("[Trace] Entering getDvdJson..")
    dvdJson = {}
    dvdJson['key'] = key
    dvdJson['title'] = dvd.title
    dvdJson['type'] = dvd.type
    dvdJson['year'] = dvd.year
    if dvd.thumbNailLink:
        dvdJson['thumbNailLink'] = dvd.thumbNailLink
    else:
        dvdJson['thumbNailLink'] = '/thumbs/Shawshank.jpg'
    
    if dvd.directors:
        dvdJson['directors'] = ",".join(dvd.directors)
    else:
        dvdJson['directors'] = ""
    if dvd.actors:
        dvdJson['actors'] = ",".join(dvd.actors)
    else:
        dvdJson['actors'] = ""
    if dvd.musicDirectors:
        dvdJson['musicDirectors'] = ",".join(dvd.musicDirectors)
    else:
        dvdJson['musicDirectors'] = ""
    if dvd.imdbLink:
        dvdJson['imdbLink'] = dvd.imdbLink
    else:
        dvdJson['imdbLink'] = ""
    return dvdJson

def myDvdDelete(request):
    logger.info("[Trace] Entering myDvdDelete...")
    user = users.GetCurrentUser()
    if user is None:
        logger.info("User not logged in.. redirecting...")
        return response.login(request)
    try:
        logger.info("User logged in as.. (%s)" %(str(user)))
        key = request.GET.get('key')
        logger.info('key to delete = ' + str(key))
        try:
            logger.info("DB operation (get) started...")            
            dvd = Dvd.get(key)
            logger.info("DB operation (get) done...")
        except Exception, e:
            statusStr = 'Exception thrown while getting record matching key (%s). Reason (%s)' % (str(key), str(e))
            return response.done(request, user, "{\"status\":\"" + statusStr + "\"}")
        if dvd is None:
            return response.done(request, user, "{\"status\":\"Key not found\"}")
        elif dvd.owner == user:
            logger.info("DB operation (delete) started...") 
            dvd.delete()
            logger.info("Deleted")
        else :
            logger.error("Hmm.. wrong owner ????")
            return response.done(request, user, "{\"status\":\"Key not owned by current user\"}")
    except Exception, e:
        logger.error(sys.exc_info())
        statusStr = 'Exception throw. Key (%s). Reason (%s)' % (str(key), str(e))
        return response.done(request, user, "{\"status\":\"" + statusStr + "\"}")
    return response.done(request, user, '{\"status\":\"ok\"}')
                
def myDvdAdd(request):
    logger.info('[TRACE] Entering myDvdAdd...')
    user = users.GetCurrentUser()
    if user is None:
        logger.info("User not logged in.. redirecting...")
        return response.login(request)
    if user:
        try:
            key = 0
            title = request.POST.get('title')
            title = title.decode('utf-8')
            dvd = Dvd(title=title)
            dvd.type = request.POST.get('type')
            if dvd.type:
                dvd.type = dvd.type.decode('utf-8')
            else:
                dvd.type = 'DVD'.encode('utf-8')
            
            directors = request.POST.get('directors')
            if directors:
                # Note that the strings are encoded as utf-8 chars by default. So we need to decode it as such,
                # before we can do any string operation like split on them.
                directors = directors.decode('utf-8');
                dvd.directors = directors.split(',')
                
            actors = request.POST.get('actors')
            if actors:
                actors = actors.decode('utf-8')
                dvd.actors = actors.split(',')
                
            musicDirectors = request.POST.get('musicDirectors')
            if musicDirectors:
                musicDirectors = musicDirectors.decode('utf-8')
                dvd.musicDirectors = musicDirectors.split(',')
                
            #TODO - Do we need to decode everything as 'utf-8' ? Currently only when we need to any operation
            #on the string, then we decode it as utf-8. So if any of the below strings also get processed, then
            #remember to decode it first as utf-8 to be safe
                
            dvd.imdbLink = request.POST.get('imdb')
            dvd.thumbNailLink = request.POST.get('thumbNailLink')
            dvd.year = request.POST.get('year')
            if dvd.year is None:
                dvd.year = '????'
            dvd.owner = user
            logger.info("Starting DB operation (put) for user (%s)..." %(str(user)))
            key = dvd.put();
            logger.info("Done...")
            dvdJson = getDvdJson(dvd, key)
            return response.respond(request, user, 'dvdjson', dvdJson)
        except Exception, e:
            logger.error(sys.exc_info())
            exc_type, exc_value, exc_traceback = sys.exc_info()
#            statusStr = 'Exception throw. Reason (%s)' % (str(key), str(e))
            statusStr = 'Exception throw. Reason (%s) on line (%d)' % (str(e), exc_traceback.tb_lineno)
            return response.done(request, user, "{\"status\":\"" + statusStr + "\"}")
            
def getSimilarDvds(request):
    logger.info('[TRACE] Entering getSimilarDvds...')
    user = users.GetCurrentUser()
    if user is None:
        logger.info("User not logged in.. redirecting...")
        return response.login(request)
    if user:
        try:
            title = request.GET.get('title')
            type = request.GET.get('type')
            logger.info('Starting IMDB access..')
            imdbHttp = IMDb(accessSystem='http', useModule='beautifulsoup', loggingLevel='error')
            logger.info('Searching for movie (%s)...' %(title))
            results = imdbHttp.search_movie(title, 1)
            logger.info('Iterating thro the results')
            dvdJsonList=[]
            for movie in results:
                dvdJson = {}
                dvdJson['type']=type
                dvdJson['title']=movie['title']
                dvdJson['year']=movie['year']
                movieID = movie.movieID
                dvdJson['imdbLink'] = 'http://www.imdb.com/title/tt' + movieID
                imdbHttp.update(movie, ('main'))
                thumbNail = movie.get('cover url')
                if thumbNail:
                    dvdJson['thumbNailLink'] = thumbNail
                else :
                    dvdJson['thumbNailLink'] = "/thumbs/noImage.png"

                directors = movie.get('director')
                directorsList = ""
                if directors:
                    for director in directors:
                        directorsList += director['name'] + ", "
#                        dvdJson['directors'] = ",".join(director['name'])
                else :
                    directorsList = "<unknown>"
                dvdJson['directors'] = directorsList
                        
                actors = movie.get('cast')
                actorsList = ""
                if actors:
                    for actor in actors:
                        actorsList += actor['name'] + ", "
#                        dvdJson['actors'] = ",".join(actor['name'])
                else :
                    actorsList = "<unknown>"
                dvdJson['actors'] = actorsList
                            
                dvdJson['musicDirectors'] = "<not sure>"
                dvdJsonList.append(dvdJson)
            params={}
            params['dvd_list'] =  dvdJsonList
            logger.info('All data parsed.. sending response...')
            return response.respond(request, user, 'dvdListIMDBJson', params)
        except Exception, e:
            logger.error(sys.exc_info())
            statusStr = 'Exception thrown. Reason (%s)' % (str(e))
            return response.done(request, user, "{\"status\":\"" + statusStr + "\"}")